package com.xyy.saas.payment.adpater.unionpay;

import com.alibaba.fastjson.JSON;
import com.unionpay.acp.sdk.SDKConfig;
import com.unionpay.acp.sdk.SDKUtil;
import com.unionpay.acp.sdksample.multicert.DemoBase;
import com.xyy.framework.redis.core.RedisClient;
import com.xyy.saas.payment.adpater.channel.setting.ChannelSettingManager;
import com.xyy.saas.payment.common.exception.PaymentException;
import com.xyy.saas.payment.cores.enums.ResultCodeEnum;
import com.xyy.saas.payment.cores.vo.UnionPayConfigVo;
import com.xyy.saas.payment.dao.model.RefundOrder;
import com.xyy.saas.payment.payment.core.bo.RefundBO;
import com.xyy.saas.payment.payment.core.dto.RefundDto;
import com.xyy.saas.payment.service.PayResultOrderService;
import com.xyy.saas.payment.payment.core.service.PrePayOrderService;
import com.xyy.saas.payment.util.DateUtil;
import com.xyy.saas.payment.util.UnionPayUtils;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.Date;
import java.util.Map;
import java.util.SortedMap;

/**
 * @author niuhaiyu
 * @ClassName AbstractUnionPayChannelHandler
 * @Description 描述
 * @Date 2021/7/8 下午8:43
 */
public abstract  class AbstractUnionPayChannelHandler implements UnionPayChannelHandler {

    private static final Logger LOGGER = LoggerFactory.getLogger(AbstractUnionPayChannelHandler.class);

    @Autowired
    protected UnionPayUtils unionPayUtils;
    @Autowired
    protected RedisClient redisClient;

    @Autowired
    protected PrePayOrderService prePayOrderService;

    @Autowired
    protected ChannelSettingManager channelSettingManager;

    @Autowired
    protected PayResultOrderService payResultOrderService;


    @Override
    public RefundBO refund(RefundDto refundDto, String channelUser) throws PaymentException {
        RefundBO refundBO =  new RefundBO();

        try {

            UnionPayConfigVo unionPayConfigVo = channelSettingManager.getUnionPayConfig(refundDto.getBusinessOrderType(), refundDto.getPayMode());

            if (unionPayConfigVo == null) {
                throw new PaymentException(ResultCodeEnum.UNIONPAY_CONFIG_NOT_EXITS);
            }

            unionPayUtils.init(unionPayConfigVo);

            SortedMap paramsMap = joinRefundRequestData(refundDto);
            //生成签名
            Map<String, String> signMap = unionPayUtils.signData(paramsMap);

            LOGGER.info("UnionPayAdapter#refund invoke param pay_no:{},param:{}", refundDto.getPayNo(), JSON.toJSONString(signMap));

            //发送请求
            Map<String, String> resultMap = unionPayUtils.post(SDKConfig.getConfig().getBackRequestUrl(),signMap);

            LOGGER.info("UnionPayAdapter#refund invoke remote pay_no:{},result:{}", refundDto.getPayNo(), JSON.toJSONString(resultMap));

            if (!SDKUtil.validate(resultMap, DemoBase.encoding)){
                throw new PaymentException(ResultCodeEnum.SIGN_ERROR);
            }

            if("00".equals(resultMap.get("respCode"))){
                //拼接业务处理信息
                String orderId = resultMap.get("orderId");
                String txnTime = resultMap.get("txnTime");
                refundBO.setChannelRefundNo(orderId);
                refundBO.setDate(StringUtils.isEmpty(txnTime)? new Date() : DateUtil.parase(txnTime, DateUtil.YYYYMMDDHHMMSS));
                refundBO.setRefundNo(refundDto.getRefundNo());
                refundBO.setChannelRefundNo("");
                refundBO.setStatus(RefundOrder.STATUS_FINISH);

                return refundBO;

            }else{
                refundBO.setRefundNo(refundDto.getRefundNo());
                refundBO.setChannelRefundNo("");
                refundBO.setStatus(RefundOrder.STATUS_FAIL);
                LOGGER.info("UnionPayAdapter#refund create fail pay_no:{},result:{}", refundDto.getPayNo(), JSON.toJSONString(resultMap));
                return refundBO;
            }


        }
        catch (PaymentException e) {
            LOGGER.error("UnionPayAdapter#refund error refundDto:{}", JSON.toJSON(refundDto), e);
            throw e;
        }
        catch (Exception e) {
            LOGGER.error("UnionPayAdapter#refund error refundDto:{}", JSON.toJSON(refundDto), e);
            throw new PaymentException(ResultCodeEnum.DEFAULT_ERROR, e);

        }
    }

}
